﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Pixels.Logic
{
    public class Map : IEnumerable<Tile> {
        private Tile[,] _tiles;

        public int Width {
            get {
                if (_tiles == null) return -1;
                return _tiles.GetLength(0);
            }
        }

        public int Height {
            get {
                if (_tiles == null) return -1;
                return _tiles.GetLength(1);
            }
        }

        public void create(int width, int height) {
            _tiles = new Tile[width, height];
            for (int iy = 0; iy < height; iy++)
                for (int ix = 0; ix < width; ix++) {
                    _tiles[ix, iy] = new Tile(this, ix, iy);
                }
        }

        public Tile this[int x, int y] {
            get  { 
                // warning : not particularly performant, will optimize
                if (x < 0) return null; if (x >= Width) return null;
                if (y < 0) return null; if (y >= Height) return null;
                return _tiles[x, y];
            }
        }

        IEnumerator<Tile> IEnumerable<Tile>.GetEnumerator() {
            foreach (var t in _tiles) yield return t;
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
            return _tiles.GetEnumerator();
        }

        public void recalcDiscoverabilityMap() {
            var disc = new HashSet<Tile>();
            foreach (var tile in this) {
                if (tile.visibility == Visibility.visible) disc.Add(tile);
            }
            var adj = new HashSet<Tile>();
            foreach (var tile in disc) {
                adj.UnionWith(tile.getAdjacentTiles());
                adj.UnionWith(tile.getDiagonalTiles());
            }
            adj.ExceptWith(disc);



            allExternalHandles = new HashSet<IAssignationTarget>();
            foreach (var tile in adj) {
                tile.visibility = Visibility.discoverable;
                allExternalHandles.Add(tile.discoveryHandle);
            }

        }

        // external handle = not a structure but a atarget
        public ISet<IAssignationTarget> allExternalHandles;

        internal ScoutingReward scoutTile(Tile tile) {
            tile.visibility = Visibility.visible;

            if( Ur.Random.QuickRnd.d100 > 85)
                return ScoutingReward.createRandomReward();
            else
                return null;
            
        }

        internal Tile[] selectTiles(int x0, int y0, int w, int h) {

            var l = new List<Tile>();
            for (var y = y0; y < y0 + h; y++)
            for (var x = x0; x < x0 + w; x++) {
                var t =  this[x, y];
                if (t != null) l.Add(t);
            }
            return l.ToArray();
        }

        internal Tile[] selectRing(int xc, int yc, int ring_distance) {
            var l = new List<Tile>();
            for (var y = yc - ring_distance; y <= yc + ring_distance; y++)
                for (var x = xc - ring_distance; x <= xc  + ring_distance; x++) {
                    if ((x == xc - ring_distance) || (x == xc + ring_distance) || (y == yc + ring_distance) || (y == yc - ring_distance)) {
                        l.Add(this[x, y]);
                    }                    
                }
            return l.ToArray();
        }
    }
}
